package com.baoyang.tool.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Component
public class JwtUtils {

    private static final String JWT_SECRET = "baoyangSecretKey123456";
    private static final long EXPIRATION = 1000L * 60 * 60 * 24 * 30; // 30天（毫秒）
    private static final long REDIS_EXPIRATION = 60 * 60 * 24 * 30; // Redis中存储30天（秒）

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 生成token
     */
    public String generateToken(String userName, Long userId) {
        String token = Jwts.builder()
                .setSubject(userName)
                .claim("userId", userId)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
                .signWith(SignatureAlgorithm.HS256, JWT_SECRET)
                .compact();
        // 存入redis，设置12小时过期
        stringRedisTemplate.opsForValue().set(getRedisKey(token), "1", REDIS_EXPIRATION, TimeUnit.SECONDS);
        // 验证数据是否存储成功
        if(Boolean.FALSE.equals(stringRedisTemplate.hasKey(getRedisKey(token)))) {
            System.out.println("Token存储失败");
            throw new RuntimeException("Token存储失败");
        }
        return token;
    }

    /**
     * 从token中获取用户名
     */
    public String getPhoneFromToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(JWT_SECRET)
                .parseClaimsJws(token)
                .getBody();
        return claims.getSubject();
    }

    /**
     * 从token中获取用户ID
     */
    public Long getUserIdFromToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(JWT_SECRET)
                .parseClaimsJws(token)
                .getBody();
        return claims.get("userId", Long.class);
    }

    /**
     * 验证token是否有效
     */
    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(JWT_SECRET).parseClaimsJws(token);
            // 校验redis中是否存在
            String redisVal = stringRedisTemplate.opsForValue().get(getRedisKey(token));
            return redisVal != null;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 检查token是否过期
     */
    public boolean isTokenExpired(String token) {
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(JWT_SECRET)
                    .parseClaimsJws(token)
                    .getBody();
            return claims.getExpiration().before(new Date());
        } catch (Exception e) {
            return true;
        }
    }

    /**
     * 刷新token在Redis中的过期时间
     * 当用户进行操作时调用此方法
     */
    public void refreshTokenExpiration(String token) {
        try {
            // 检查token是否在Redis中存在
            String redisVal = stringRedisTemplate.opsForValue().get(getRedisKey(token));
            if (redisVal != null) {
                // 重新设置过期时间为一个月
                stringRedisTemplate.expire(getRedisKey(token), REDIS_EXPIRATION, TimeUnit.SECONDS);
            }
        } catch (Exception e) {
            // 如果刷新失败，记录日志但不影响正常流程
            System.err.println("刷新token过期时间失败: " + e.getMessage());
        }
    }

    // 让token失效
    public void invalidateToken(String token) {
        stringRedisTemplate.delete(getRedisKey(token));
    }

    // redis key生成
    private String getRedisKey(String token) {
        return "login:token:" + token;
    }
}